import 'package:flutter/material.dart';
import 'dart:async';

class StreamDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StreamDemo'),
        elevation: 0.0,
      ),
      body: StreamHomeDemo(),
    );
  }
}

class StreamHomeDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => StreamHomeDemoState();
}

class StreamHomeDemoState extends State<StreamHomeDemo> {
  ///可以使用 StreamSubscription 进行 暂停 重新 取消订阅  使用Stream 的 listen方法 返回 StreamSubscription 对象
  StreamSubscription streamDemoSubscription;

  ///使用StreamController 来控制Stream
  StreamController<String> streamController;

  StreamSink _streamSink; //Sink 有水槽的意思

  @override
  void initState() {
    super.initState();
//    Stream<String> _streamDemo = Stream.fromFuture(fetchData());

//    streamController = StreamController<String>();

    streamController = StreamController.broadcast(); //多种Controller 的Stream；
    _streamSink = streamController.sink;
    streamDemoSubscription = streamController.stream.listen(onData,
        onDone: onStreamDone, onError: onStreamError); //Stream添加回调方法

    streamDemoSubscription = streamController.stream.listen(onDataTow,
        onDone: onStreamDoneTow, onError: onStreamErrorTow); //Stream添加回调方法
  }

  @override
  void dispose() {
    streamController.close();
    super.dispose();
  }

  ///数据获取成功
  onData(streamData) {
    print(streamData);
  }

  ///获取Stream 完成
  onStreamDone() {
    print('onStreamDone');
  }

  ///获取Stream失败
  onStreamError(error) {
    print(error);
  }

  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 5));
    return 'hello jack';
//    throw 'something error';
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        StreamBuilder(
            //使用StreamBuilder 构建小部件 当stream的数据变化时会重新构建小部件
            stream: streamController.stream,
            initialData: '...',
            builder: (context, snaop) {
              return Text(snaop.data);
            }),
        Row(
          children: <Widget>[
            Wrap(
              spacing: 4.0,
              runSpacing: 4.0,
              children: <Widget>[
                FlatButton(
                  child: Text(
                    'add',
                    style: TextStyle(color: Colors.black),
                  ),
                  color: Colors.amber,
                  onPressed: _addDataToStream,
                ),
                FlatButton(
                  child: Text(
                    'pause',
                    style: TextStyle(color: Colors.black),
                  ),
                  color: Colors.amber,
                  onPressed: _onPauseSubcritpion,
                ),
                FlatButton(
                  child: Text(
                    'resume',
                    style: TextStyle(color: Colors.black),
                  ),
                  color: Colors.amber,
                  onPressed: _onResumeSubcritpion,
                ),
                FlatButton(
                  child: Text(
                    'cancle',
                    style: TextStyle(color: Colors.black),
                  ),
                  color: Colors.amber,
                  onPressed: _onCanleSubcritpion,
                ),
              ],
            )
          ],
        ),
      ],
    ));
  }

  void _onPauseSubcritpion() {
    streamDemoSubscription.pause();
    print('_onPauseSubcritpion');
  }

  void _onResumeSubcritpion() {
    streamDemoSubscription.resume();
    print('_onResumeSubcritpion');
  }

  void _onCanleSubcritpion() {
    streamDemoSubscription.cancel();
    print('_onCanleSubcritpion');
  }

  void _addDataToStream() async {
    print('add data To Stream');
    String data = await fetchData();
    _streamSink.add(data);
  }

  void onStreamDoneTow() {
    print('onStreamDoneTow');
  }

  void onDataTow(streamData) {
    print('streamdataTow = $streamData');
  }

  onStreamErrorTow(error) {
    print(error);
  }
}
